package com.kingyun.gpsinspection.purificationservice.services.tdm.innerservice.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cqhilink.api.common.utils.UniqueUtil;
import com.kingyun.gpsinspection.purificationservice.common.utils.ConstantUtil;
import com.kingyun.gpsinspection.purificationservice.common.utils.FileTypeUtil;
import com.kingyun.gpsinspection.purificationservice.dao.mapper.tdm.*;
import com.kingyun.gpsinspection.purificationservice.facade.model.File;
import com.kingyun.gpsinspection.purificationservice.facade.model.jsm.EmployeeVo;
import com.kingyun.gpsinspection.purificationservice.facade.model.jsm.EntityVo;
import com.kingyun.gpsinspection.purificationservice.facade.model.jsm.Organization;
import com.kingyun.gpsinspection.purificationservice.facade.model.jsm.RedisValue;
import com.kingyun.gpsinspection.purificationservice.facade.model.tdm.*;
import com.kingyun.gpsinspection.purificationservice.facade.service.jsm.OutEntityService;
import com.kingyun.gpsinspection.purificationservice.facade.service.jsm.OutOrganizationService;
import com.kingyun.gpsinspection.purificationservice.facade.service.tdm.HazardIdentificationService;
import com.kingyun.gpsinspection.purificationservice.facade.service.tdm.IBMBPMService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.net.URLEncoder;
import java.util.Date;
import java.util.List;

/**
 * 危害因素辨识业务层
 * Created by sugongche on 2017/2/6
 */
public class HazardIdentificationServiceImpl implements HazardIdentificationService {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    // BPM
    @Autowired
    public IBMBPMService ibmbpmService;
    @Autowired
    private HazardIdentificationMapper hazardIdentificationMapper;
    @Autowired
    public TaskLinkMapper taskLinkMapper;
    @Autowired
    public TdmWorkOrderMapper tdmWorkOrderMapper;
    @Autowired
    public TdmHazardMapper tdmHazardMapper;
    @Autowired
    private TdmFileMapper tdmFileMapper;
    @Autowired
    private TdmTaskRelationMapper tdmTaskRelationMapper;
    @Autowired(required = false)
    private OutEntityService outEntityService;
    @Autowired(required = false)
    public OutOrganizationService outOrganizationService;

    /**
     * 保存
     * 注意：解开启事务，不能抛异常
     *
     * @param redisValue
     * @param employeeVo
     * @param hazardIdentification 属地监督
     * @param hazard
     * @param taskRelation
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int save(RedisValue redisValue, EmployeeVo employeeVo, HazardIdentification hazardIdentification, Hazard hazard, String uploadFiles, String deletedFiles, TaskRelation taskRelation) {
        if (hazardIdentification == null || hazard == null) {
            return 0;
        }

        int a = 0;
        //String username="deadmin";
        //String password="deadmin";
        String username = redisValue.getLoginName();//用户名
        String password = redisValue.getPassWord();//密码

        //开始流程
        String result = ibmbpmService.openBPM(employeeVo, hazardIdentification.getTaskType(), username, password, null);
        //如果没有权限直接返回99
        if (result.equals("WorkSpaceError")) {
            return 99;
        }
        String piid = "";//流程实例ID
        String tkiid = "";//任务节点ID
        String name = ""; //第一个任务实例节点的名称

        //获得返回值
        JSONObject resultObj = JSONObject.parseObject(result);
        if (resultObj != null) {
            String status = (String) resultObj.get("status");
            //开始流程成功
            if (status != null && status.equals("200")) {
                //获取data属性的值
                JSONObject dataObj = (JSONObject) resultObj.get("data");
                //获取tasks属性的值：只有一个元素的数组，元素包含流程实例id和第一个节点的任务id
                JSONArray itemsArray = (JSONArray) dataObj.get("tasks");
                for (int i = 0; i < itemsArray.size(); i++) {//循环json数组
                    JSONObject ob = (JSONObject) itemsArray.get(i);//得到json对象
                    piid = ob.getString("piid");//piid这里是列名称，获取json对象中列名为piid的值
                    tkiid = ob.getString("tkiid");//tkiid这里是列名称，获取json对象中列名为tkiid的值
                    name = ob.getString("name");//name是列名称，获取json对象中列名为name的值
                }

                //执行第一个任务节点
                result = ibmbpmService.completeTask(username, password, tkiid, null);
                //获得返回值
                resultObj = JSONObject.parseObject(result);
                if (resultObj != null) {
                    status = (String) resultObj.get("status");

                    //完成任务成功
                    if (status != null && status.equals("200")) {
                        //第零步：先保存任务相关信息
                        //直接创建危害因素辨识时hazardId为空：区分从危害因素发起
                        if (StringUtils.isBlank(hazard.getHazardId())) {
                            //保存危害因素
                            hazard.setHazardId(UniqueUtil.uuid());
                            hazard.setCreateUserId(employeeVo.getEmployeeId());
                            hazard.setModifyUserId(employeeVo.getEmployeeId());
                            //设置对象组织：提出方法
                            setOrgIdByCondition(employeeVo, hazard);
                            //状态0正常；1是删除
                            hazard.setIsDelete((short) 0);
                            a += tdmHazardMapper.insertNew(hazard);
                        }

                        //第一步：后保存任务信息
                        //保存属地监督：必须设置流程实例ID
                        hazardIdentification.setFlowId(piid);
                        //当前节点：从0开始
                        hazardIdentification.setNode((short) 0);
                        a += saveBean(employeeVo, hazardIdentification, hazard);
                        // 判断关联任务对象是否为空
                        if (StringUtils.isNotBlank(taskRelation.getMasterTaskId())) {
                            // 关系表主键
                            taskRelation.setTaskRelationId(UniqueUtil.uuid());
                            // 主任务ID和主任务类型已经包含在relation对象中
                            taskRelation.setRelatedTaskId(hazardIdentification.getHazardIdentificationId());
                            taskRelation.setRelatedTaskType(hazardIdentification.getTaskType());
                            // 保存关联任务信息
                            a += tdmTaskRelationMapper.insert(taskRelation);
                        }

                        //第二步：保存附件；根据任务信息
                        a += saveAttach(hazardIdentification, uploadFiles, deletedFiles);

                        //第三步：保存任务环节
                        TaskLink taskLink = new TaskLink();
                        taskLink.setPiPiid(piid);//流程实例ID
                        taskLink.setTkiid(tkiid);//任务节点ID
                        taskLink.setTaskLinkName(name);//任务节点名称
                        taskLink.setAuditStatus((short) 1);//第一个节点默认设置通过
                        //保存任务相关信息：先保存任务环节
                        a += saveTaskLink(employeeVo, hazardIdentification, taskLink);
                    } else {
                        logger.error("完成危害因素辨识第一个任务节点失败！");
                    }
                } else {
                    logger.error("完成危害因素辨识第一个任务节点无返回值！");
                }
            } else {
                logger.error("发起危害因素辨识失败！");
            }
        } else {
            logger.error("发起危害因素辨识无返回值！");
        }

        return a;
    }

    /**
     * 设置危害对象所属组织
     *
     * @param employeeVo
     * @param hazard
     */
    public void setOrgIdByCondition(EmployeeVo employeeVo, Hazard hazard) {
        //设置危害对象所属组织
        if (StringUtils.isNotBlank(hazard.getEntityId())) {
            try {
                EntityVo entityVo = outEntityService.getEntityByEntityId(hazard.getEntityId());
                //问题对象ID是生产实体
                if (entityVo != null) {
                    hazard.setOrgId(entityVo.getParentOrgId());
                    //问题对象ID不是生产实体，而是组织ID
                }
                //问题对象ID不是生产实体，而是组织ID
                Organization organization = outOrganizationService.queryOrganization(hazard.getEntityId());
                if (organization != null) {
                    hazard.setOrgId(hazard.getEntityId());
                }
                if (entityVo == null && organization == null) {
                    hazard.setOrgId(employeeVo.getOrgId());
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        } else {
            hazard.setOrgId(employeeVo.getOrgId());
        }
    }

    /**
     * 保存危害因素辨识任务对象
     *
     * @param employeeVo
     * @param hazardIdentification
     * @param hazard
     * @return
     */
    public int saveBean(EmployeeVo employeeVo, HazardIdentification hazardIdentification, Hazard hazard) {
        int a = 0;

        hazardIdentification.setHazardId(hazard.getHazardId());
        hazardIdentification.setHazardIdentificationId(UniqueUtil.uuid());
        hazardIdentification.setCreateUserId(employeeVo.getEmployeeId());
        hazardIdentification.setModifyUserId(employeeVo.getEmployeeId());
        //-1 正在审核；1 审核通过；0审核不通过
        hazardIdentification.setAuditStatus((short) -1);
        //状态0正常；1是删除
        hazardIdentification.setIsDelete((short) 0);
        //状态1是启用；0是关闭
        hazardIdentification.setIsEnable((short) 1);
        //1 审核处理中；2 执行中；3 已完成
        hazardIdentification.setTaskStatus((short) 1);
        //创建时间
        hazardIdentification.setCreateTime(new Date());
        //修改时间
        hazardIdentification.setModifyTime(new Date());
        //新增发起任务信息
        a = hazardIdentificationMapper.insert(hazardIdentification);

        return a;
    }

    /**
     * 根据Bean的信息保存附件（新增和删除）
     *
     * @param hazardIdentification
     * @param uploadFiles
     * @return
     */
    public int saveAttach(HazardIdentification hazardIdentification, String uploadFiles, String deletedFiles) {
        int a = 0;

        //保存附件
        if (StringUtils.isNotBlank(uploadFiles)) {
            //强制转换成集合
            List<File> listFiles = JSON.parseArray(uploadFiles, File.class);
            //重新设置附件属性
            for (int i = 0; i < listFiles.size(); i++) {
                File _file = listFiles.get(i);
                //设置主键
                _file.setFileId(UniqueUtil.uuid());
                //设置业务数据id
                _file.setBusinessId(hazardIdentification.getHazardIdentificationId());
                _file.setFileType((short) FileTypeUtil.getFileTypeByFileName(_file.getFileName()));
            }
            //必须判断非空
            if (listFiles != null && listFiles.size() > 0) {
                a = tdmFileMapper.insertByList(listFiles);
            }
        }

        //需要删除的附件信息
        if (StringUtils.isNotBlank(deletedFiles)) {
            //强制转换成集合
            List<File> listFiles = JSON.parseArray(deletedFiles, File.class);
            if (listFiles != null && listFiles.size() > 0) {
                int len = listFiles.size();
                for (int i = 0; i < len; i++) {
                    File _file = listFiles.get(i);
                    a += tdmFileMapper.deleteByPrimaryKey(_file.getFileId());
                }
            }
        }

        return a;
    }

    /**
     * 更新
     *
     * @param redisValue
     * @param employeeVo
     * @param hazardIdentification
     * @param hazard
     * @param taskLink
     * @param uploadFiles
     * @param deletedFiles
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int update(RedisValue redisValue, EmployeeVo employeeVo, HazardIdentification hazardIdentification, Hazard hazard, TaskLink taskLink, String uploadFiles, String deletedFiles) {
        if (hazardIdentification == null) {
            return 0;
        }

        //标志变量
        int a = 0;

        //String username="deadmin";
        //String password="deadmin";
        String username = redisValue.getLoginName();//用户名
        String password = redisValue.getPassWord();//密码
        String result = ibmbpmService.completeTask(username, password, taskLink.getTkiid(), null);

        //处理返回值为空串：执行了但是没有返回值
        if ("".equals(result)) {
            logger.info("完成“" + taskLink.getTaskLinkName() + "”返回值为空串！");
        } else {
            //获得返回值
            JSONObject resultObj = JSONObject.parseObject(result);
            if (resultObj != null) {
                String status = (String) resultObj.get("status");
                //开始流程成功
                if (status != null && status.equals("200")) {
                    //第一步：更新任务信息；修改人必填
                    hazardIdentification.setModifyUserId(employeeVo.getEmployeeId());
                    a += hazardIdentificationMapper.updateByPrimaryKeyNew(hazardIdentification);

                    //第二步：更新任务相关信息；修改人必填
                    hazard.setModifyUserId(employeeVo.getEmployeeId());
                    a += tdmHazardMapper.updateByPrimaryKeyNew(hazard);

                    //第三步：更新附件信息：新增+删除
                    a += saveAttach(hazardIdentification, uploadFiles, deletedFiles);

                    //第四步：更新任务环节信息；工单信息已经更新：此处无需再保存工单
                    //注意：必须拿到当前任务的信息，因为从页面上传来的任务信息没有node值
                    HazardIdentification hazardIdentificationNew = hazardIdentificationMapper.selectByPrimaryKeyNew(hazardIdentification.getHazardIdentificationId());
                    a += saveTaskLink(employeeVo, hazardIdentificationNew, taskLink);
                } else {
                    logger.error("完成“" + taskLink.getTaskLinkName() + "”返回状态非200！");
                }
            } else {
                logger.error("完成“" + taskLink.getTaskLinkName() + "”返回值非json字符串！！");
            }
        }

        return a;
    }

    /**
     * 根据主键查询bean
     *
     * @param hazardIdentificationId
     * @return
     */
    @Override
    public HazardIdentification queryBeanById(String hazardIdentificationId) throws Exception {
        if (StringUtils.isBlank(hazardIdentificationId)) {
            return null;
        }

        HazardIdentification hazardIdentification = hazardIdentificationMapper.selectByPrimaryKey(hazardIdentificationId);

        return hazardIdentification;
    }

    /**
     * 根据ID查询封装对象
     *
     * @return
     */
    @Override
    public HazardIdentificationVo findVoById(String id) throws Exception {
        if (StringUtils.isBlank(id)) {
            return null;
        }

        HazardIdentificationVo hazardIdentificationVo = hazardIdentificationMapper.selectByPrimaryKeyNew(id);

        return hazardIdentificationVo;
    }

    /**
     * 根据任务实例ID查询任务表和任务环节表
     *
     * @param piPiid
     * @return
     */
    @Override
    public HazardIdentificationVo findByPiPiid(String piPiid) {
        if (StringUtils.isBlank(piPiid)) {
            return null;
        }

        HazardIdentificationVo hazardIdentificationVo = hazardIdentificationMapper.findVoByPiPiid(piPiid);

        return hazardIdentificationVo;
    }

    /**
     * 审核时完成任务和保存信息
     *
     * @param redisValue
     * @param employeeVo
     * @param taskLink
     * @param hazardIdentification
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int saveByAudit(RedisValue redisValue, EmployeeVo employeeVo, TaskLink taskLink, HazardIdentification hazardIdentification) throws Exception {
        //用户信息
        //String username = "deadmin";
        //String password = "deadmin";
        String username = redisValue.getLoginName();//用户名
        String password = redisValue.getPassWord();//密码
        String parameter = null;
        if (taskLink.getAuditStatus() != null) {
            //获取前台页面传来的审核是否通过的值：是用taskLink接收的
            parameter = URLEncoder.encode("{\"approved\":" + taskLink.getAuditStatus() + "}", "UTF-8");
        }
        String result = ibmbpmService.completeTask(username, password, taskLink.getTkiid(), parameter);

        //标志变量
        int a = 0;
        //处理返回值为空串：执行了但是没有返回值
        if ("".equals(result)) {
            logger.info("完成“" + taskLink.getTaskLinkName() + "”返回值为空串！");
        } else {
            //获得返回值
            JSONObject resultObj = JSONObject.parseObject(result);
            if (resultObj != null) {
                String status = (String) resultObj.get("status");
                //开始流程成功
                if (status != null && status.equals("200")) {
                    a = saveTaskLink(employeeVo, hazardIdentification, taskLink);
                } else {
                    logger.error("完成“" + taskLink.getTaskLinkName() + "”返回状态非200！");
                }
            } else {
                logger.error("完成“" + taskLink.getTaskLinkName() + "”返回值非json字符串！！");
            }
        }

        return a;
    }

    /**
     * 现场操作
     *
     * @param redisValue
     * @param employeeVo
     * @param hazardIdentification
     * @param taskLink
     * @return
     */
    @Override
    public int saveByStep(RedisValue redisValue, EmployeeVo employeeVo, HazardIdentification hazardIdentification, TaskLink taskLink) {
        //用户信息
        //String username = "deadmin";
        //String password = "deadmin";
        String username = redisValue.getLoginName();//用户名
        String password = redisValue.getPassWord();//密码
        String result = ibmbpmService.completeTask(username, password, taskLink.getTkiid(), null);

        //标志变量
        int a = 0;
        //处理返回值为空串：执行了但是没有返回值
        if ("".equals(result)) {
            logger.info("完成“" + taskLink.getTaskLinkName() + "”返回值为空串！");
        } else {
            //获得返回值
            JSONObject resultObj = JSONObject.parseObject(result);
            if (resultObj != null) {
                String status = (String) resultObj.get("status");
                //开始流程成功
                if (status != null && status.equals("200")) {
                    a = saveTaskLink(employeeVo, hazardIdentification, taskLink);
                } else {
                    logger.error("完成“" + taskLink.getTaskLinkName() + "”返回状态非200！");
                }
            } else {
                logger.error("完成“" + taskLink.getTaskLinkName() + "”返回值非json字符串！");
            }
        }

        return a;
    }

    /**
     * 保存任务相关信息：先保存任务环节，再保存工单
     *
     * @param employeeVo
     * @param hazardIdentification
     * @param taskLink
     * @return
     */
    public int saveTaskLink(EmployeeVo employeeVo, HazardIdentification hazardIdentification, TaskLink taskLink) {
        //标志变量
        int a = 0;
        //表单提交的审核状态
        Short auditStatus = taskLink.getAuditStatus();

        //添加任务环节
        taskLink.setTaskLinkId(UniqueUtil.uuid());
        //任务发起表存的是当前节点
        taskLink.setNode(hazardIdentification.getNode());
        taskLink.setTaskType(hazardIdentification.getTaskType());
        taskLink.setTaskId(hazardIdentification.getHazardIdentificationId());
        //没有审核：完成任务默认审核通过
        taskLink.setAuditStatus(auditStatus == null ? (short) 1 : auditStatus);
        //执行人ID：当前用户ID
        taskLink.setUserId(employeeVo.getEmployeeId());
        //执行人组织
        taskLink.setOrgId(employeeVo.getOrgId());
        a += taskLinkMapper.insertNew(taskLink);

        //更新当前节点：节点前进一步
        a += hazardIdentificationMapper.updateCurrentNodeById(hazardIdentification);

        //没有审核或者审核通过：走到下一个节点，审核状态默认为通过
        if (auditStatus == null) {
            hazardIdentification.setAuditStatus((short) 1);
            a += hazardIdentificationMapper.updateAuditStatusById(hazardIdentification);
            //审核通过
        } else if (auditStatus != null && auditStatus == 1) {
            hazardIdentification.setAuditStatus((short) 1);
            a += hazardIdentificationMapper.updateAuditStatusById(hazardIdentification);
            //驳回：回到第一个节点
        } else if (auditStatus != null && auditStatus == 0) {
            hazardIdentification.setAuditStatus((short) 0);
            a += hazardIdentificationMapper.updateAuditStatusById(hazardIdentification);
        }

        //审核完成：状态进入执行中
        if (auditStatus != null && auditStatus == 1 && ConstantUtil.JOINT_HEARING.equals(taskLink.getTaskLinkName())) {
            a += hazardIdentificationMapper.updateTaskStatusById(hazardIdentification);
        }

        //完成任务时：更新任务状态和实际完成时间
        if (ConstantUtil.CREATE_RELATED_TASK.equals(taskLink.getTaskLinkName())) {
            a += hazardIdentificationMapper.updateFinishById(hazardIdentification);
        }

        return a;
    }
}
